﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;

namespace HYView
{
	[Regeneration(RegenerationOption.Manual)]
	[Transaction(TransactionMode.Manual)]
	internal class CmdViewRotate : YJKCommandManual
	{
		protected override Result YJKExcute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
			CmdViewType types = (CmdViewType)3;
			if (SwitchView.SetUsableView(types, cmdData) != Autodesk.Revit.UI.Result.Succeeded)
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			Document document = cmdData.Application.ActiveUIDocument.Document;
			Autodesk.Revit.DB.View activeView = cmdData.Application.ActiveUIDocument.ActiveView;
			if (activeView.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).AsElementId().ToString() == "-1")
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
				filteredElementCollector.WhereElementIsNotElementType();
				if (filteredElementCollector != null)
				{
					filteredElementCollector.OfCategory(BuiltInCategory.OST_VolumeOfInterest);
				}
				IList<Element> list = filteredElementCollector.ToElements();
				if (list.Count <= 0)
				{
					YJKMessageBox.Show("当前模型没有范围框，请先创建范围框。");
					return base.YJKExcute(cmdData, ref message, elements);
				}
				if (new DlgSetCorp(document, activeView, list).ShowDialog() != DialogResult.OK)
				{
					return base.YJKExcute(cmdData, ref message, elements);
				}
			}
			Parameter parameter = activeView.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP);
			try
			{
				Reference reference = this.m_uiDoc.Selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, new CmdViewRotate.LineObj(), "请选择线性参照物对象");
				Line line = CmdViewRotate.LineObj.GetLine(document.GetElement(reference));
				Transaction transaction = new Transaction(document, "Rotate");
				try
				{
					transaction.Start();
					activeView.CropBoxVisible = false;
					Element element = document.GetElement(parameter.AsElementId());
					BoundingBoxXYZ boundingBoxXYZ = element.get_BoundingBox(activeView);
					XYZ xyz = boundingBoxXYZ.Min.Add(boundingBoxXYZ.Max).Divide(2.0);
					Line line2 = Line.CreateBound(xyz, new XYZ(xyz.X, xyz.Y, -1.0));
					double num = 0.0;
					ExtensibleStorageManager.ReadRampExtensibleStorage(element, ref num);
					if (num != 0.0)
					{
						ElementTransformUtils.RotateElement(document, parameter.AsElementId(), line2, num);
						num = CmdViewRotate.rotate(document, parameter, line2, line, element, num);
					}
					else
					{
						num = CmdViewRotate.rotate(document, parameter, line2, line, element, num);
					}
					transaction.Commit();
				}
				catch
				{
					transaction.RollBack();
				}
			}
			catch
			{
			}
			return base.YJKExcute(cmdData, ref message, elements);
		}

		private static double rotate(Autodesk.Revit.DB.Document doc, Parameter param1, Line axis, Line line, Element elem, double angle)
		{
			angle = Math.PI - XYZ.BasisX.AngleTo(line.Direction);
			if (angle > Math.PI*.5)
			{
				angle = Math.PI*2 - angle;
			}
			ElementTransformUtils.RotateElement(doc, param1.AsElementId(), axis, -angle);
			ExtensibleStorageManager.WriteRampExtensibleStorage(elem, angle);
			return angle;
		}

		public class LineObj : ISelectionFilter
		{
			public static Line GetLine(Element lineObj)
			{
				Line result = null;
				if (lineObj is Wall)
				{
					result = (((LocationCurve)((Wall)lineObj).Location).Curve as Line);
				}
				else if (lineObj is Grid)
				{
					result = (((Grid)lineObj).Curve as Line);
				}
				else if (lineObj is ModelLine)
				{
					result = (((ModelLine)lineObj).GeometryCurve as Line);
				}
				else if (lineObj is DetailLine)
				{
					result = (((LocationCurve)((DetailLine)lineObj).Location).Curve as Line);
				}
				return result;
			}

			public bool AllowElement(Element elem)
			{
				if (elem is Wall)
				{
					return ((LocationCurve)((Wall)elem).Location).Curve is Line;
				}
				if (elem is Grid)
				{
					return ((Grid)elem).Curve is Line;
				}
				if (elem is ModelLine)
				{
					return ((ModelLine)elem).GeometryCurve is Line;
				}
				return elem is DetailLine && ((LocationCurve)((DetailLine)elem).Location).Curve is Line;
			}

			public bool AllowReference(Reference reference, XYZ position)
			{
				return false;
			}
		}
	}
}
